什么是分布式系统
分布式系统是由多台独立计算机通过网络连接协同工作的系统。对于用户来说,整个系统中的多台服务器是完全透明的 -- 用户只知道在访问一个服务,但不知道这个服务背后有多少台机器在支撑。
在分布式架构中,通常会在业务服务器前端部署多台负载均衡服务器(如 Nginx),用户的请求先到达负载均衡层,再被分发到后端的实际业务服务器上。负载均衡可以根据每台服务器的硬件配置、承载能力、网络条件来设置不同的权重。
分布式与微服务的区别
| 维度 | 分布式系统 | 微服务架构 |
|---|---|---|
| 核心关注点 | 部署层面,分散压力 | 架构层面,分散能力 |
| 部署方式 | 多台机器部署相同业务 | 不同机器部署不同业务模块 |
| 耦合度 | 较高(相同业务的横向扩展) | 较低(不同服务独立运行) |
| 维护成本 | 相对较低 | 较高,服务间通信和治理更复杂 |
用一个形象的比喻:分布式系统是多台机器共同承担同一个业务(比如 10 台服务器都跑完整的用户管理系统),微服务是把用户管理系统拆成鉴权、用户信息、订单等独立服务,每个服务可能运行在多台机器上。
服务治理
当系统从单体演变为分布式或微服务架构后,就需要面对服务治理的问题。服务治理涵盖以下几个方面:
服务注册与发现
系统中有哪些服务在运行?扩展了几台服务器?这些服务器属于哪个服务?这些问题需要服务注册与发现机制来解决。常见的工具有 Consul、Nacos、Etcd 等。
版本控制与迭代
服务的版本如何管理?新旧版本如何平滑切换?灰度发布如何实现?
运行监控
服务的运行状态、响应时间、错误率等指标需要实时监控。Prometheus + Grafana 是目前最流行的监控方案之一。
故障定位
当某个服务出现异常时,如何快速定位是哪个节点、哪台服务器出了问题?分布式链路追踪(如 Zipkin、Jaeger)可以帮助解决。
安全管控
服务间的通信是否安全?API 是否有认证和授权?这些都需要在服务治理层面考虑。
分布式系统的核心问题
数据一致性
在分布式系统中,数据一致性是最棘手的问题之一。以下是一个典型场景:
假设服务 A 和服务 B 都连接到同一个数据库集群(一主多从)。服务 A 正在写入数据,但数据还未完全同步到从库。此时服务 B 从从库读取数据,读到的可能是旧数据,导致数据不一致。
服务A → 写入主库 → 主从同步(有延迟)→ 从库
服务B → 读取从库 ← 可能读到旧数据
text
这个问题在极端情况下更为严重:如果某个机房发生断电或网络中断,整个片区的数据库都无法访问,此时数据同步完全停止,其他机房的服务可能读到不一致的数据。
异地容灾策略
为了解决上述问题,通常会采用异地多活的容灾策略:
- 在 A 地(AD)和 B 地(BD)分别部署独立的主从数据库集群
- 正常情况下,两地的主库同时写入,数据双向同步
- 当 A 地发生故障时,负载均衡会将流量全部切换到 B 地
- B 地的服务读取 BD 的从库数据,保障系统继续运行
用户请求 → 负载均衡 → [AD服务集群, BD服务集群]
↓ ↓
AD主库 ←同步→ BD主库
↓ ↓
AD从库 BD从库
text
网络延迟与不可靠
分布式系统依赖网络通信,而网络本质上是不可靠的。网络延迟、丢包、分区故障都可能导致服务调用超时或失败。
分布式系统的应用场景
分布式系统适合以下场景:
- 高并发 -- 搜索引擎、电商秒杀、社交网络
- 海量数据 -- 大数据分析、日志处理
- 高可用 -- 金融系统、在线支付、物联网平台
Java 生态中的服务治理中间件
了解 Java 生态中的微服务中间件有助于拓宽视野,但不应该生搬硬套到 Node.js 中:
| 类别 | Java 生态工具 | 说明 |
|---|---|---|
| 服务注册发现 | Nacos, Consul, Eureka | 服务的注册、发现和健康检查 |
| 服务配置 | Spring Cloud Config | 集中管理服务配置 |
| 服务熔断 | Hystrix, Resilience4j | 熔断、降级、限流 |
| 网关 | Spring Cloud Gateway | 服务路由、鉴权、限流 |
| 负载均衡 | Ribbon, LoadBalancer | 客户端负载均衡 |
| 链路追踪 | Zipkin, SkyWalking | 分布式调用链追踪 |
| 日志采集 | ELK Stack | 日志的收集、存储和检索 |
Node.js 侧并不需要完全照搬这些中间件,应根据实际业务需求选择合适的方案,很多基础设施能力(如服务发现、负载均衡、健康检查)在 K8s 中已经内置支持。
↑